﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;
using System.Web.UI.WebControls;

using System.Text.RegularExpressions;
using System.Data;
using System.Web.UI;
using System.Collections;

namespace 书籍与目录检索
{
    class ChapterSearch
    {
        mainForm myForm;
        string sConnStr;
        SqlConnection odcConnection=new SqlConnection();
        SqlCommand odCommand;
        SqlDataSource ds = new SqlDataSource();
        System.Windows.Forms.Label lbFindStatus;
        System.Windows.Forms.Label lbFindCount;
        int iSearchType;

        delegate void SetTextCallback(string status, int amount, string message);//设置委托
        /// <summary>
        /// 检索章节初始化
        /// </summary>
        /// <param name="_myForm">窗体</param>
        /// <param name="_lbFindCount">一个label用于存储找到数目</param>
        /// <param name="_sConnStr">数据库连接字符串</param>
        /// <param name="iType">检索类型</param>
        public ChapterSearch(mainForm _myForm,System.Windows.Forms.Label _lbFindStatus, System.Windows.Forms.Label _lbFindCount,string _sConnStr,int _iSearchType)
        {
            myForm = _myForm;
            lbFindCount = _lbFindCount;
            lbFindStatus = _lbFindStatus;
            sConnStr = _sConnStr;
            iSearchType = _iSearchType;
            odcConnection.ConnectionString = sConnStr;
            ds.ConnectionString = sConnStr;
        }
        public void Search()
        {
            try
            {
                odcConnection.Open();
                odCommand = odcConnection.CreateCommand();
                ds.SelectCommand = "select List_BookID,List_SiteID,List_ID,List_BookName,List_SiteName,List_LastChapter,List_URL,List_Reg from ls_List where  List_ID in  ";
                ds.SelectCommand += "(select top 100 List_ID from ls_List where List_Active=1 and List_Level=1 order by List_LastTime)";
                odCommand.CommandText = "update ls_List set List_LastTime=getdate() where List_ID in (select top 100 List_ID from ls_List where List_Active=1 and List_Level=1 order by List_LastTime)";

                switch (iSearchType)
                {
                    case ChapterSearchType.Hot:
                        ds.SelectCommand = "select List_BookID,List_SiteID,List_ID,List_BookName,List_SiteName,List_LastChapter,List_URL,List_Reg from ls_List where  List_ID in  ";
                        ds.SelectCommand += "(select top 100 List_ID from ls_List where List_Active=1 and List_Level=5 order by List_LastTime)";
                        odCommand.CommandText = "update ls_List set List_LastTime=getdate() where List_ID in (select top 100 List_ID from ls_List where List_Active=1 and List_Level=5 order by List_LastTime)";
                        break;
                    case ChapterSearchType.Cold:
                        ds.SelectCommand = "select List_BookID,List_SiteID,List_ID,List_BookName,List_SiteName,List_LastChapter,List_URL,List_Reg from ls_List where  List_ID in  ";
                        ds.SelectCommand += "(select top 100 List_ID from ls_List where List_Active=1 and List_Level=1 order by List_LastTime)";
                        odCommand.CommandText = "update ls_List set List_LastTime=getdate() where List_ID in (select top 100 List_ID from ls_List where List_Active=1 and List_Level=1 order by List_LastTime)";
                        break;
                    case ChapterSearchType.BookShelf:
                        ds.SelectCommand = "select List_BookID,List_SiteID,List_ID,List_BookName,List_SiteName,List_LastChapter,List_URL,List_Reg from ls_List where  List_ID in  ";
                        ds.SelectCommand += "(select top 100 List_ID from ls_List where List_Active=1 and exists (select * from ls_MyBook where MyBook_BookID=List_BookID)order by List_LastTime2)";
                        odCommand.CommandText = "update ls_List set List_LastTime2=getdate() where List_ID in (select top 100 List_ID from ls_List where List_Active=1 and exists (select * from ls_MyBook where MyBook_BookID=List_BookID) order by List_LastTime2)";
                        break; ;
                    case ChapterSearchType.Failed:
                        ds.SelectCommand = "select List_BookID,List_SiteID,List_ID,List_BookName,List_SiteName,List_LastChapter,List_URL,List_Reg from ls_List where  List_ID in  ";
                        ds.SelectCommand += "(select top 100 List_ID from ls_List where List_Active=0 order by List_LastTime)";
                        odCommand.CommandText = "update ls_List set List_LastTime=getdate() where List_ID in (select top 100 List_ID from ls_List where List_Active=0 order by List_LastTime)";
                        break;
                    default:
                        break;
                }
                DataView dv = (DataView)ds.Select(DataSourceSelectArguments.Empty);
                odCommand.ExecuteNonQuery();
                searchChapter(dv);
                dv.Dispose();
            }
            catch (Exception ex)
            {
                setWorkStatus("", 0, "search()失败：" + ex.Message + ex.Data);
            }
            finally
            {
                odcConnection.Dispose();
                ds.Dispose();
            }
        }
        /// <summary>
        /// 搜索数据集中所有章节
        /// </summary>
        /// <param name="dv"></param>
        private void searchChapter(DataView dv)
        {
            string sHtml;//访问得到的网页HTML
            string sBookIndex;
            string sRecNo;
            string sRegChapterList;
            string sBookID;
            string sBookName;
            string sSiteID;
            string sSiteName;
            string sLastChapter;
            string sBookURLHead;
            ArrayList alURL = new ArrayList(); //章节列表
            ArrayList alName = new ArrayList(); //章节名称列表
            for (int i = 0; i < dv.Count; i++)
            {

                try
                {
                    sBookIndex = dv[i]["List_URL"].ToString();
                    sRecNo = dv[i]["List_ID"].ToString();
                    sRegChapterList = dv[i]["List_Reg"].ToString();
                    sBookID = dv[i]["List_BookID"].ToString();
                    sBookName = dv[i]["List_BookName"].ToString();
                    sSiteID = dv[i]["List_SiteID"].ToString();
                    sSiteName = dv[i]["List_SiteName"].ToString();
                    sLastChapter = dv[i]["List_LastChapter"].ToString();
                    sBookURLHead = GetData.getPathFromURL(sBookIndex);
                    setWorkStatus("《" + sBookName + "》-" + sSiteName, 0, "");

                    alURL.Clear();
                    alName.Clear();

                    sHtml = GetData.getHtml(sBookIndex);

                    bool bfind = false;//设置查找标记，开始为否

                    if (sHtml == null || sHtml == "")//如果没有获得任何信息，也就是访问中出现了错误，增加其failcount值
                    {

                        odCommand.CommandText = "update ls_List set List_FailCount=List_FailCount+1,List_Active=0 from ls_List where List_ID=" + sRecNo;
                        odCommand.ExecuteNonQuery();
                        if (iSearchType != ChapterSearchType.Failed) //当前线程不是失败按钮创建的话。输出
                            setWorkStatus("", 0, "获取" + sSiteName + "上小说《" + sBookName + "》失败：" + sBookIndex);
                        continue;
                    }
                    else//有内容的话开始解析文件
                    {
                        Match match = Regex.Match(sHtml, sRegChapterList, RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.RightToLeft);

                        if (!match.Success)
                        {
                            //如果返回内容了，但是查找却不成功，那就需要检查正则表达式了。
                            odCommand.CommandText = "update ls_List set List_RegFailCount=List_RegFailCount+1,List_Active=0 where List_ID=" + sRecNo;
                            odCommand.ExecuteNonQuery();
                            continue;
                        }
                        else
                        {

                            //将所有的收集到两个字符串数组中。然后反向输出就好。
                            int count = 0; //最多检索条数
                            while (match.Success&&count<6)
                            {
                                string schapterurl = match.Groups[1].Value;
                                string schaptername = match.Groups[2].Value.Trim();
                                schaptername = Regex.Replace(schaptername, "[\\s]*\\s", " ", RegexOptions.IgnoreCase | RegexOptions.Multiline);
                                schaptername = Regex.Replace(schaptername, "'", "", RegexOptions.IgnoreCase | RegexOptions.Multiline);
                                count++;
                                //如果找到了，就可以结束循环。
                                if (schapterurl == sLastChapter)
                                {

                                    bfind = true;
                                    break; //结束循环
                                }
                                //还没有找到，就先存起来。
                                else
                                {
                                    alURL.Add(schapterurl);
                                    alName.Add(schaptername);
                                }
                                match = match.NextMatch();
                            }
                        }//正则表达式校验结束
                    }//有内容的解析结束

                    if (bfind == true)
                    {//如果找到了最后章节，全部输出来。

                        if (alURL.Count > 0)
                        {
                            odCommand.CommandText = "update ls_List set List_LastChapter='" + alURL[0] + "',List_LastTitle='" + alName[0] + "',List_NoNewCount=0,List_RegFailCount=0,List_FailCount=0,List_UpdateTime=getdate(),List_Active=1 where List_ID=" + sRecNo;
                            odCommand.ExecuteNonQuery();

                            odCommand.CommandText = "update ls_Book set Book_LastChapter='" + alName[0] + "',Book_lasttime=getdate() where Book_ID=" + sBookID;
                            odCommand.ExecuteNonQuery();

                            for (int j = alURL.Count - 1; j >= 0; j--)
                            {
                                string urltemp = sBookURLHead + alURL[j];
                                odCommand.CommandText = "insert into ls_Chapter(Chapter_BookID,Chapter_SiteID,Chapter_Title,Chapter_URL) select " + sBookID + "," + sSiteID + ",'" + alName[j] + "','" + urltemp + "'  where not exists (select * from ls_Chapter where Chapter_URL='" + urltemp + "')";
                                if (odCommand.ExecuteNonQuery() > 0)
                                    setWorkStatus("", 1, alName[j].ToString());

                            }
                        }
                        else
                        {
                            odCommand.CommandText = "update ls_List set List_NoNewCount=List_NoNewCount+1,List_Active=1 where List_ID=" + sRecNo;
                            odCommand.ExecuteNonQuery();
                        }
                    }

                    //没有找到最后一章，但是却有至少一条记录
                    if (bfind == false && alURL.Count > 0)
                    {
                        string urltemp = sBookURLHead + alURL[0];
                        odCommand.CommandText = "insert into ls_Chapter(Chapter_BookID,Chapter_SiteID,Chapter_Title,Chapter_URL) select " + sBookID + "," + sSiteID + ",'" + alName[0] + "','" + urltemp + "'  where not exists (select * from ls_Chapter where Chapter_URL='" + urltemp + "')";
                        //如果插入记录成功，也就是原来数据库中没有记录。那就更新book表、list表
                        if (odCommand.ExecuteNonQuery() > 0)
                        {
                            odCommand.CommandText = "update ls_List set List_LastChapter='" + alURL[0] + "',List_LastTitle='" + alName[0] + "',List_NoNewCount=0,List_RegFailCount=0,List_FailCount=0,List_UpdateTime=getdate(),List_Active=1 where List_ID=" + sRecNo;
                            odCommand.ExecuteNonQuery();

                            odCommand.CommandText = "update ls_Book set Book_LastChapter='" + alName[0] + "' where Book_ID=" + sBookID;
                            odCommand.ExecuteNonQuery();

                            setWorkStatus("", 1, alName[0].ToString());
                        }

                    }
                }
                catch (Exception ex)
                {
                    setWorkStatus("", 0, "检索章节异常" + ex.Message + ex.Data + "\r\n");
                }
             
            }
            
        }
        /// <summary>
        /// 设置工作状态
        /// </summary>
        /// <param name="status">状态信息</param>
        /// <param name="amount">增加数量</param>
        /// <param name="message">更新信息</param>
        public void setWorkStatus(string status, int amount, string message)
        {
            //来设置工作状态，解决多线程下不能设置问题
            try
            {
                if (myForm.InvokeRequired)
                {
                    SetTextCallback d = new SetTextCallback(setWorkStatus);
                    myForm.Invoke(d, new object[] { status,amount, message });

                }
                else
                {  
                    if (status != "")
                        lbFindStatus.Text= status;

                    if (message != "")
                        myForm.tbChapterMessage.Text += message + "\r\n";

                    if (amount != 0)
                    {
                        myForm.tslChapterCount.Text = (Convert.ToInt32(myForm.tslChapterCount.Text) + amount).ToString();
                        lbFindCount.Text = (Convert.ToInt32(lbFindCount.Text) + amount).ToString();
                    }
                }
            }
            catch (Exception ex)
            {
                string info = ex.Message + ex.Data;
                // MessageBox.Show("设置工作状态" + ex.Message + ex.Message + ex.Data);
                setWorkStatus("", 0, "设置工作状态错误" + ex.Message + ex.Data + "\r\n");

            }

        }
    }
}
